package view;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.HashMap;
import java.util.Map;

import main.Log;
import model.Model;
import model.entity.BasicEntity;
import model.item.EquipmentSlot;

public class EquipmentOverlay extends Overlay {

	private final int buttonSize = 40;//widht and height of icons (in pixels)
	private final int spacing = 10;//spacing between icons (in pixels)
	
	private BasicEntity be;
	private BufferedImage img;//used for buffering
	private Point upperLeft;//point at which starting starts
	private Map<Model, MouseListener> itemToListener;
	
	public EquipmentOverlay(Dimension sizeOfOuterContainer, BasicEntity basicEntity,
			Point upperLeft, Map<Model, MouseListener> itemToListener) {
		super(sizeOfOuterContainer);
		this.be = basicEntity;
		if(be != null) { be.register( this ); }
		this.itemToListener = (itemToListener != null) ? 
				itemToListener : new HashMap<Model, MouseListener>();
		this.upperLeft = ( upperLeft != null ) ? upperLeft : new Point( 0,0 );
	}
	
	public void onResize() {} //TODO implement
	
	public void setEntity( BasicEntity entity ) {
		this.be = entity;
		be.register( this );
	}
	
	public void update ( Model m ) {
		this.updateSubscribers();//controller will load new listeners
		this.invalidateImg();//it will be re-drawn form scratch next time
	}
	
	public void setListeners( Map<Model, MouseListener> itemToListener ) {
		this.itemToListener = itemToListener;
		this.invalidateImg();
	}
	
	public void drawOverlay( Graphics g ) {
		if( imgIsBuffered() ) {
			g.drawImage( img, 0, 0, null );
		}//else, draw it from scratch
		super.removeAllButtons();
		img = new BufferedImage(super.getOuterDimension().width,
				super.getOuterDimension().height, BufferedImage.TYPE_INT_ARGB );
		Graphics g2 = img.getGraphics();//draw on th buffered image
		drawHelper( g2, getHelmetOffset(), EquipmentSlot.HEAD );//draw helmet
		drawHelper( g2, getArmorOffset(), EquipmentSlot.UPPER_BODY );//draw armor
		drawHelper( g2, getLeftArmOffset(), EquipmentSlot.LEFT_HAND );//draw left hand
		drawHelper( g2, getRightArmOffset(), EquipmentSlot.RIGHT_HAND );//draw right hand
		drawHelper( g2, getTrouserOffset(), EquipmentSlot.LOWER_BODY );//draw trousers
		//draw buffered image on g
		g.drawImage( img, 0, 0, null);
	}
	
	private void drawHelper( Graphics g, Point offset, EquipmentSlot equipmentSlot ) {
		if ( be == null || be.getEquipment() == null || itemToListener == null) {
			drawIcon( g, "", null, offset );
			return ;
		}
		Model m = be.getEquipment().getEquipment( equipmentSlot );
		if( m == null) {
			drawIcon( g, "", null, offset );
			return ; 
		}
		drawIcon( g, m.getName(), itemToListener.get(m), offset );
	}
	
	private Point getHelmetOffset() {
		return new Point( 1 * ( buttonSize + spacing ), 0 * ( buttonSize + spacing ) );
	}
	
	private Point getArmorOffset() {
		return new Point( 1 * ( buttonSize + spacing ), ( buttonSize + spacing ) );
	}
	
	private Point getLeftArmOffset() {
		return new Point( 0 * ( buttonSize + spacing ), ( buttonSize + spacing ) );
	}
	
	private Point getRightArmOffset() {
		return new Point( 2 * ( buttonSize + spacing ), ( buttonSize + spacing ) );
	}
	
	private Point getTrouserOffset() {
		return new Point( ( buttonSize + spacing ), 2 * ( buttonSize + spacing ) );
	}
	
	private void drawIcon( Graphics g, String modelName, MouseListener listener, 
			Point offset ) {
		Rectangle rect = new Rectangle( upperLeft.x + offset.x,
				upperLeft.y + offset.y,
				buttonSize, buttonSize);
		String name = ( modelName != null ) ? modelName : "";
		Image img = ModelToImage.getImage( name );
		GameButton b = new GameButton( name, rect,  img);
		if( listener != null) { b.attachListener( listener ); }
		super.addButton( b );
	}
	
	private boolean imgIsBuffered() {
		return img != null;
	}
	
	private void invalidateImg() {
		img = null;
	}
	
	private boolean haveBasicEntity() {
		return be != null;
	}
}
